package com.ash.nio.tcp.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class SelectorDemo {

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        serverSocketChannel.bind(new InetSocketAddress("localhost", 8081));
        serverSocketChannel.configureBlocking(false);

        Selector selector = Selector.open();

        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {

            int select = selector.select();
            if (select <= 0) {
                System.out.println("没有事件要处理");
                continue;
            }
            System.out.println("有事件要处理");

            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();

            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();

                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);

                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }


                if (selectionKey.isReadable()) {
                    ByteBuffer attachment = (ByteBuffer) selectionKey.attachment();

                    SocketChannel channel = (SocketChannel) selectionKey.channel();


                    try {
                        int read = channel.read(attachment);
                        if (read == -1) { // 对方关闭了连接
                            System.out.println("客户端已关闭连接");
                            closeAndDeregisterChannel(selectionKey, channel);
                            continue;
                        }

                        System.out.println(new String(attachment.array()));
                    } catch (IOException e) {
                        System.out.println("异常关闭连接");
                        closeAndDeregisterChannel(selectionKey, channel);
                        continue;
                    }
                }

                iterator.remove();
            }

        }
    }

    // 定义一个方法用于关闭通道并从选择器中取消注册
    private static void closeAndDeregisterChannel(SelectionKey selectionKey, SelectableChannel channel) {
        try {
            selectionKey.cancel();
            if (channel instanceof SocketChannel) {
                ((SocketChannel) channel).close();
            }
        } catch (IOException e) {
            System.err.println("关闭通道时发生异常: " + e.getMessage());
        }
    }
}
